import dashscope
from dashscope import Generation, SpeechSynthesizer
import logging
import os
import uuid
from typing import Optional, Tuple, AsyncGenerator
import aiofiles
import asyncio
from concurrent.futures import ThreadPoolExecutor
import wave
import io

from config import settings
from backend.config.poets_knowledge import get_poet_system_prompt

logger = logging.getLogger(__name__)

class QwenPoetService:
    """诗人专用的Qwen服务类"""
    
    def __init__(self):
        """初始化服务"""
        dashscope.api_key = settings.dashscope_api_key
        self.executor = ThreadPoolExecutor(max_workers=4)
        self.current_poet = "liqingzhao"  # 默认使用李清照
        
    def set_poet(self, poet_id: str):
        """设置当前诗人角色"""
        self.current_poet = poet_id
        logger.info(f"切换到诗人角色: {poet_id}")
    
    async def generate_poet_response(self, message: str) -> str:
        """
        生成诗人风格的AI回复
        
        Args:
            message: 用户输入消息
            
        Returns:
            str: 诗人风格的AI回复文本
        """
        try:
            # 获取诗人特定的系统提示词
            system_prompt = get_poet_system_prompt(self.current_poet)
            
            # 构建消息列表
            messages = [
                {
                    'role': 'system',
                    'content': system_prompt
                },
                {
                    'role': 'user',
                    'content': message
                }
            ]
            
            # 异步调用通义千问API
            loop = asyncio.get_event_loop()
            response = await loop.run_in_executor(
                self.executor,
                self._sync_generate_response,
                messages
            )
            
            return response
            
        except Exception as e:
            logger.error(f"生成诗人回复失败: {str(e)}")
            raise Exception(f"诗人回复生成失败: {str(e)}")
    
    def _sync_generate_response(self, messages: list) -> str:
        """同步调用通义千问API"""
        # 使用更适合诗人风格的参数
        response = Generation.call(
            model='qwen-plus',  # 使用qwen-plus模型
            messages=messages,
            result_format='message',
            stream=False,
            incremental_output=False,
            temperature=0.8,  # 稍高的温度以增加文学性和创造力
            max_tokens=1500   # 增加最大 tokens 以容纳更长的回复
        )
        
        if response.status_code == 200:
            return response.output.choices[0].message.content
        else:
            raise Exception(f"API调用失败: {response.message}")
    
    async def synthesize_poet_speech(self, text: str, voice: str = "zhichu") -> Tuple[str, float, list]:
        """
        合成诗人风格的语音
        
        Args:
            text: 要合成的文本
            voice: 语音类型，默认为"zhichu"
            
        Returns:
            Tuple[str, float, list]: (音频文件URL, 音频时长, 句子时间戳列表)
        """
        try:
            # 异步调用语音合成
            loop = asyncio.get_event_loop()
            audio_data = await loop.run_in_executor(
                self.executor,
                self._sync_synthesize_speech,
                text, voice
            )
            
            # 保存音频文件
            audio_url, duration, timestamps = await self._save_audio_file(audio_data)
            
            return audio_url, duration, timestamps
            
        except Exception as e:
            logger.error(f"诗人语音合成失败: {str(e)}")
            raise Exception(f"诗人语音合成失败: {str(e)}")
    
    def _sync_synthesize_speech(self, text: str, voice: str) -> bytes:
        """同步调用语音合成API"""
        # 为诗人选择合适的语音参数
        # 对不同诗人可以有不同的语音风格配置
        if self.current_poet == "liqingzhao":  # 李清照 - 女性，婉约
            voice_params = {
                "model": "sambert-zhishu-v1",
                "voice": "zhishu",
                "format": "wav",
                "sample_rate": 16000,
                "speed": 0.9,  # 稍慢以体现典雅
                "pitch": 1.0
            }
        elif self.current_poet == "libai":  # 李白 - 男性，豪放
            voice_params = {
                "model": "sambert-zhihao-v1",
                "voice": "zhihao",
                "format": "wav",
                "sample_rate": 16000,
                "speed": 1.1,  # 稍快以体现豪放
                "pitch": 1.0
            }
        elif self.current_poet == "dufu":  # 杜甫 - 男性，深沉
            voice_params = {
                "model": "sambert-zhide-v1",
                "voice": "zhide",
                "format": "wav",
                "sample_rate": 16000,
                "speed": 0.85,  # 慢以体现深沉
                "pitch": 0.9
            }
        elif self.current_poet == "sushi":  # 苏轼 - 男性，豁达
            voice_params = {
                "model": "sambert-zhilun-v1",
                "voice": "zhilun",
                "format": "wav",
                "sample_rate": 16000,
                "speed": 1.0,
                "pitch": 1.05  # 稍高以体现豁达
            }
        else:  # 默认语音配置
            voice_params = {
                "model": f"sambert-{voice}-v1" if voice else "sambert-zhichu-v1",
                "voice": voice if voice else "zhichu",
                "format": "wav",
                "sample_rate": 16000,
                "speed": 1.0,
                "pitch": 1.0
            }
        
        # 调用API进行语音合成
        response = SpeechSynthesizer.call(
            model=voice_params["model"],
            text=text,
            voice=voice_params["voice"],
            format=voice_params["format"],
            sample_rate=voice_params["sample_rate"],
            speed=voice_params["speed"],
            pitch=voice_params["pitch"]
        )
        
        if response.status_code == 200:
            return response.audio_data
        else:
            raise Exception(f"语音合成失败: {response.message}")
    
    async def _save_audio_file(self, audio_data: bytes) -> Tuple[str, float, list]:
        """保存音频文件并返回URL、时长和时间戳"""
        try:
            # 确保音频目录存在
            os.makedirs(settings.audio_dir, exist_ok=True)
            
            # 生成唯一文件名
            filename = f"tts_{uuid.uuid4().hex}.mp3"
            file_path = os.path.join(settings.audio_dir, filename)
            
            # 计算音频时长
            duration = self._calculate_audio_duration(audio_data)
            
            # 保存音频文件
            async with aiofiles.open(file_path, 'wb') as f:
                await f.write(audio_data)
            
            # 生成时间戳（这里使用简化的时间戳生成逻辑）
            timestamps = self._generate_timestamps(duration, audio_data)
            
            # 生成音频URL
            audio_url = f"{settings.api_url}/audio/{filename}"
            
            logger.info(f"诗人音频文件已保存: {filename}, 时长: {duration:.2f}秒")
            
            return audio_url, duration, timestamps
            
        except Exception as e:
            logger.error(f"保存诗人音频文件失败: {str(e)}")
            raise Exception(f"保存诗人音频文件失败: {str(e)}")
    
    def _calculate_audio_duration(self, audio_data: bytes) -> float:
        """计算音频时长"""
        try:
            # 这里使用简化的音频时长计算方法
            # 在实际应用中，应该根据音频格式和采样率进行精确计算
            # 对于WAV格式，可以使用wave模块解析
            if audio_data.startswith(b'RIFF'):
                with io.BytesIO(audio_data) as f:
                    with wave.open(f, 'rb') as wf:
                        frames = wf.getnframes()
                        rate = wf.getframerate()
                        duration = frames / float(rate)
                        return duration
            # 对于其他格式，返回估计值
            return len(audio_data) / 16000.0  # 假设16kHz采样率，单声道
        except:
            # 如果计算失败，返回默认值
            return 3.0
    
    def _generate_timestamps(self, duration: float, audio_data: bytes) -> list:
        """生成句子时间戳列表"""
        # 这里使用简化的时间戳生成逻辑
        # 在实际应用中，应该使用更复杂的音频分析技术
        timestamps = []
        
        # 示例：将音频均匀分割成3-5个部分作为时间戳
        parts = max(3, min(5, int(duration / 2) + 1))
        interval = duration / parts
        
        for i in range(parts):
            timestamps.append({
                "start": round(i * interval, 2),
                "end": round(min((i + 1) * interval, duration), 2)
            })
        
        return timestamps
    
    async def generate_poet_response_stream(self, message: str) -> AsyncGenerator[dict, None]:
        """
        生成诗人风格的流式AI回复
        
        Args:
            message: 用户输入消息
            
        Yields:
            dict: 包含流式回复内容的字典
        """
        try:
            # 获取诗人特定的系统提示词
            system_prompt = get_poet_system_prompt(self.current_poet)
            
            # 构建消息列表
            messages = [
                {
                    'role': 'system',
                    'content': system_prompt
                },
                {
                    'role': 'user',
                    'content': message
                }
            ]
            
            # 使用同步API实现流式响应（模拟）
            loop = asyncio.get_event_loop()
            full_response = await loop.run_in_executor(
                self.executor,
                self._sync_generate_response,
                messages
            )
            
            # 模拟流式输出
            for i in range(0, len(full_response), 20):
                chunk = full_response[i:i+20]
                await asyncio.sleep(0.1)  # 模拟延迟
                yield {
                    "type": "text",
                    "content": chunk
                }
            
            # 输出结束标志
            yield {
                "type": "done",
                "content": ""
            }
            
        except Exception as e:
            logger.error(f"生成诗人流式回复失败: {str(e)}")
            yield {
                "type": "error",
                "message": f"诗人回复生成失败: {str(e)}"
            }
    
    async def analyze_poet_emotion(self, text: str) -> str:
        """
        分析诗人回复的情感
        
        Args:
            text: 诗人回复文本
            
        Returns:
            str: 情感类型
        """
        try:
            # 这里使用简化的情感分析逻辑
            # 可以根据不同诗人的特点和文本内容进行更复杂的情感分析
            emotions = {}
            
            # 统计情感相关词汇
            positive_words = ['喜', '乐', '笑', '欢', '悦', '兴', '愉', '欣']
            negative_words = ['愁', '悲', '哀', '伤', '怨', '忧', '惨', '凄']
            neutral_words = ['静', '思', '悟', '观', '叹', '论', '说', '言']
            
            for word in positive_words:
                emotions['happy'] = emotions.get('happy', 0) + text.count(word)
            
            for word in negative_words:
                emotions['sad'] = emotions.get('sad', 0) + text.count(word)
            
            for word in neutral_words:
                emotions['neutral'] = emotions.get('neutral', 0) + text.count(word)
            
            # 根据诗人特点调整权重
            if self.current_poet == 'liqingzhao':
                emotions['sad'] = emotions.get('sad', 0) * 1.5  # 李清照作品多忧愁
            elif self.current_poet == 'libai':
                emotions['happy'] = emotions.get('happy', 0) * 1.5  # 李白作品多豪放乐观
            
            # 选择最主要的情感
            if not emotions:
                return 'neutral'
            
            main_emotion = max(emotions, key=emotions.get)
            return main_emotion
            
        except Exception as e:
            logger.error(f"诗人情感分析失败: {str(e)}")
            return 'neutral'
    
    def get_poet_info(self) -> dict:
        """
        获取当前诗人的信息
        
        Returns:
            dict: 诗人信息字典
        """
        from backend.config.poets_knowledge import POETS_KNOWLEDGE
        
        if self.current_poet in POETS_KNOWLEDGE:
            return {
                "id": self.current_poet,
                "name": POETS_KNOWLEDGE[self.current_poet]["name"],
                "dynasty": POETS_KNOWLEDGE[self.current_poet]["dynasty"],
                "style": POETS_KNOWLEDGE[self.current_poet]["style"]
            }
        
        return {
            "id": "unknown",
            "name": "未知诗人",
            "dynasty": "未知朝代",
            "style": "未知风格"
        }